home *** CD-ROM | disk | FTP | other *** search
/ TOS Silver 2000 / TOS Silver 2000.iso / programm / MM2_DEV / S / COMP / TREFIN.ICL < prev   
Encoding:
Text File  |  1994-06-03  |  37.2 KB  |  3 lines

  1. ⓪ (* ------------------------⓪#Modula Compiler  /4.0/⓪#------------------------⓪#Tree-Finish⓪$⓪$28.3.85  GDOS Version⓪%8.5.85  Fehler bei Export von Variablen korrigiert⓪$10.5.85  PrtDec zehnstellig⓪$16.5.85  Fehler bei Export aus lokalen Modulen endgueltig (?) korrigiert⓪$6.10.85  (TT) Assembler-Errors in 'Massm' uebertragen⓪#22.02.86  Neuordnung der Texte⓪$2.03.86  Real-Konstanten im Hex-Format mit HexDigit {HexDigit} 'R';⓪-Wandlung von Reals jetzt ueber Strings-Modul⓪#14.04.86  Err109 nachgetragen⓪#11.07.86  Err42 entfernt⓪#08.09.86  Oktalkonstanten implementiert;⓪-Option $O waehlt Oktaldarstellung fuer Characters⓪#06.10.86  alle ErrXXX geloescht;⓪#16.10.86  statt $Oktal+ wird $Gepard- fuer Oktal-Chars abgefragt⓪#24.10.86  Constant Expressions implementiert⓪#28.10.86  Type Transfer in ConstExpr laesst verschiedene Laengen zu⓪.(mit unsinnigen Ergebnissen bei Reals)⓪$1.11.86  TravTre erkennt Relay an 0.B (Flags im Highbyte moeglich)⓪$2.11.86  in ConCard9 'D' als Suffix fuer LONGs zugelassen⓪$1.3.87 TT Anpassungen für Atari-MOS in 'ConFact'⓪$3.3.87 TT PushAcc/PopAcc nicht auf A7-Stack sondern auf ID-Stack, zus.⓪.Overflow-Abfrage⓪$24. 3.87  nicht Impl. FORWARD-Deklarationen brechen mit Fehler ab⓪/(VPKnot)⓪$07.04.87  TT RealIsUsed wird gesetzt (ConFact)⓪$18.04.87  TT ProtVar-Aufruf in VPKNOT⓪$⓪$16.06.87  ConRel: Wenn runGep & Atari-Codeerzeugung, Formatwandlung.⓪.IEEE-Fomatwandlung nur im Gepard-Modus!⓪$24.06.87  TravTr1 durchsucht auch bei lokalen Modulen die Unterbäume⓪.(wer weiß, wozu man's braucht) und ruft den Knoten-Handler⓪.auch für den Qualifier bei DefMods auf.⓪$26.06.87  Ersetzen von ^nachdeklarierte Opaues durch ^neuen Eintrag⓪.(NewOpaque)⓪$04.07.87  IDfromTree statt TravPrID zur Verarbeitung von IDs, die⓪.während TreeScan als Fehlerquelle auffallen;⓪.Procedure FwdKnot prüft auf lokale unimpl. FORWARDs⓪$08.07.87  für NewOpaque spezielle TreeScan-Routine TravTr2: erkennt⓪0Verweise auf alten Opaque-Eintrag per Relay (falls Opaque erst⓪0auf Umwegen, dann aus eigenem DefMod importiert) und ersetzt⓪0auch die.⓪.Nicht impl. Exporte jetzt durch VPKnot erkannt (statt FinExp)⓪$28.10.87  NewOpaque: Endlosschleifen beim Scannen von POINTER TO RECORD..⓪0verhindert (Markierung der bearbeiteten Einträge in Bit 3⓪0der Kennung - VARPAR-Flag, ist im globalen Level frei).⓪$07.11.87  OpqUsers: Open Array nachgetragen⓪.NewOpaque: Markierung in bit 7 statt bit 3;⓪0alle möglichen Opq-Benutzungen werden gefunden.⓪$16.11.87  NewOpq: Markierung jetzt nur noch bei Pointern, in Bit 2.⓪0Rücksetzen der Markierung durch Merken mit Pointerkette⓪0statt durch erneutes Durchsuchen!⓪$22.11.87 TT Ausgaberoutinen -> CompIO⓪$15.03.88  FinVar: Anlegen der Längenliste für Proc/Module/Tables⓪0(FinVar legt Pointerkette durch alle Einträge an, die⓪0in der Längenliste erscheinen müssen)⓪$18.05.88  FinVar: neues Format der Längenliste; enthält für jeden⓪1Eintrag Anfangsadresse und Länge.⓪$26.05.88  FacTran: Transfer von/auf 2 Byte-SETs greift nicht mehr⓪1auf falsches Wort im Akku zu⓪$29.06.88  VPKnot erkennt exportierte (nicht impl.) Prozeduren am⓪1External-Bit (bit 12) statt an bit 14.⓪%2.07.88  DoSP: holt Ergebnisse von System-Prozeduren auch bei SETs⓪1ungerader Länge richtig ab.⓪$15.12.88  ConstExpr rausgetrennt, in separates Modul⓪$10.12.89  Nachtrag vom 28.12.88⓪.TravTre: rettet beim Bearbeiten des RStacks A0⓪1(vergißt jetzt hoffentlich keine lokalen Module mehr)⓪$28.01.90 TT MovVarKnot neu; wird in M2Main.Block benutzt⓪$05.07.90 TT OpqKnot trägt nun alle Opaques in Parm-Ketten nach (hörte⓪0bisher nach dem ersten auf), auch keine Endlosschleife mehr bei⓪0rekursiven Prozedurtyp-Definitionen.⓪$18.08.90 TT Anpassung des Offsets zum lok. Record-Baum⓪$23.09.90 TT GetNameOfId findet den Namen einer ID-Beschreibung;⓪0TravTr1 & OpqKnot gehen nicht mehr durch leere Unterbäume⓪0(zumindest bei OpqKnot wurde damit ein Fehler behoben);⓪0OpqKnot berücksichtigt auch Long-OpenArrays und ProcType⓪0f. lok.Procs (Kennung 44); Importliste bei Imp-Modulen wird⓪0gekürzt (nur die wirklich benutzten IDs bleiben drin)⓪$05.03.91 TT NewOpaque/OpqKnot berücksichtigen leere Records (führte bisher⓪0zu Abstürzen).⓪$03.06.94 TT FinishData übersprang unbenutzte DATAs falsch, was zu⓪0Endlosschleifen mit Buserrors am Ende d. Speichers führte.⓪#-----------------------------------------------------⓪ *)⓪ ⓪ (* ===================================================⓪ ⓪,Low-Level Zeugs, Tree-Scanner⓪(⓪"=================================================== *)⓪ ⓪ (* Dokumentation der TravTre-Routinen:⓪ ⓪#TravTr   scannt Pervasive- und aktuelles Level sowie die auf dem⓪,Relocation Stack eingetragenen lokalen Module⓪#TravTr0  scannt Pervasive-Level sowie die auf dem Relocation Stack⓪,eingetragenen lokalen Module (also wie TravTr ohne akt. Level)⓪#TravTr1  scannt nur den Unterbaum auf (A1,D2.L)⓪#⓪#Beide Routinen verfolgen lokale Bäume von Qualifiern (lokale oder⓪#Def-Module; deren Einträge müssen z.B. auch reloziert werden), jedoch⓪#nicht von Records. Relay-Einträge werden zum Ursprung verfolgt.⓪#⓪#TravTr kann einen Eintrag mehrfach erreichen: im lokalen Modul (über⓪#den Relocation Stack) und über ein Relay bei exportierten Objekten.⓪#Die Knotenhandler müssen durch geeignete Markierung der Einträge⓪#mehrfache Bearbeitung verhindern!⓪ *)⓪ ⓪ FORWARD TravTr1;⓪ FORWARD TravTr0;⓪ ⓪ (*⓪!*  PROZEDUR (A5) AUF GESAMTEN BAUM ANWENDEN;⓪!*⓪!*  Register bei Aufruf von (A5):⓪!*    (A1,D4.L) = ^Pointerkette⓪!*  -8(A1,D4.L) = ^Identifier⓪!*  -8(A1,D2.L) = ^Eintrag zum Id⓪!*)⓪ ⓪ PROCEDURE TravTr;⓪ BEGIN⓪ ASSEMBLER⓪)MOVE.L  (A6),D2       ;GLOBAL LEVEL⓪)BEQ     TravTr9       ; IST LEER⓪)JSR     TravTr1⓪ TravTr9  JMP     TravTr0⓪ END⓪ END TravTr;⓪ ⓪ PROCEDURE TravTr0;⓪ BEGIN⓪ ASSEMBLER⓪); Relocation Stack abarbeiten (lokale Module)⓪)MOVE.L  RSTKPTR,-(A7)⓪ TravTr3  MOVE.L  (A7)+,A0⓪)MOVE.L  (A0)+,D2⓪)BNE     L1⓪)JMP     TravTr1       ;PERVASIVES⓪ L1       MOVE.L  A0,-(A7)⓪)JSR     TravTr1⓪)BRA     TravTr3⓪ END⓪ END TravTr0;⓪ ⓪ (*⓪!*   wie TravTre, jedoch wird nur der Unterbaum ab (A1,D2.L) durchsucht:⓪!*⓪!* Vorsicht: LOCXP/SetRelay verwendet D4 um an den ggf. Relay-Eintrag zu kommen.⓪!*)⓪ ⓪ PROCEDURE TravTr1;⓪ BEGIN⓪ ASSEMBLER⓪ !TRAVT1L MOVE.L  D2,-(A7)⓪)MOVE.L  -4(A1,D2.L),D2 ;LINKEN AST VERFOLGEN⓪)BEQ     TravTr2⓪)BSR     TRAVT1L⓪ !TravTr2 MOVE.L  (A7),D2⓪)MOVE.L  -8(A1,D2.L),D2 ;RECHTEN AST VERFOLGEN⓪)BEQ     TravTr4⓪)BSR     TRAVT1L⓪ !TravTr4 MOVE.L  (A7)+,D2⓪)MOVE.L  D2,D4          ;retten fuer ID-Ausgabe⓪ !TravTr5 SUBQ.L  #2,D2          ;ID WEG⓪)CMPI.W  #$FE00,-8(A1,D2.L)⓪)BCS     TravTr5        ;noch keine Endmarke⓪)MOVE.W  -10(A1,D2.L),D0 ;KENNUNG⓪)TST.B   D0⓪)BNE     TravTr7       ;KEIN RELAY⓪)MOVE.L  -14(A1,D2.L),D2⓪)ADDQ.L  #8,D2         ;UEBLICHEN OFFSET WIEDERHERSTELLEN⓪)MOVE.W  -10(A1,D2.L),D0⓪)TST.B   D0⓪)BNE     TravTr7       ;KEIN RELAY⓪)MOVE    #rTree2,D5    ;Fehler: Doppelte Relay-Verkettung⓪)JMP     SyntaxErr⓪ !TravTr7 TST.W   D0⓪)BPL     TravTr6       ;MODULA WORT⓪)CMPI.B  #15,D0        ;lokales Modul ?⓪)BEQ     L3⓪)CMPI.B  #16,D0        ;QUALIFIER?⓪)BNE     L2⓪ L3       MOVEM.L D0/D2/D4,-(A7)⓪)MOVE.L  -14(A1,D2.L),D2⓪)BEQ     L4            ;leer⓪)JSR     TravTr1       ;UNTERBAUM DURCHSUCHEN⓪ L4       MOVEM.L (A7)+,D0/D2/D4⓪ L2       JMP     (A5)⓪ !TravTr6⓪ END⓪ END TravTr1;⓪ ⓪ (*⓪(gefundenen ID waehrend TravTre in 'BadID' schreiben;⓪(wahlweise Gepard- oder Atari-Stringformat.⓪(⓪((A1,D4.L) zeigt auf PointerKette⓪(⓪((A0,D0,D1,D4)⓪ *)⓪!⓪ PROCEDURE IDfromTree;⓪ ⓪ BEGIN  ASSEMBLER⓪.LEA     BadID,A0⓪ (*$ ? RunGep: ADDQ.L  #1,A0        ;Platz für Längenzähler *)⓪.CLR.W   D1⓪&TP1     SUBQ.L  #1,D4⓪.MOVE.B  -8(A1,D4.L),D0⓪.CMP.B   #$FE,D0⓪.BCC     TP2⓪.MOVE.B  D0,0(A0,D1.W)⓪.ADDQ    #1,D1⓪.BRA     TP1⓪&TP2⓪ (*$ ? RunGep: MOVE.B  D1,-1(A0)     ;Längenzähler  *)⓪ (*$ ? RunST:  CLR.B   0(A0,D1.W)    ;Endmarke      *)⓪'END⓪ END IDfromTree;⓪ ⓪ PROCEDURE FLKNOT;⓪ BEGIN  ASSEMBLER⓪)CMPI.B #29,D0          ; Asm-Label⓪)BNE    FLKNOT1⓪)TST.L  -14(A1,D2.L)⓪)BNE    FLKNOT1⓪)JMP    AERR6⓪ FLKNOT1  CMPI.B #48,D0          ; FORWARD⓪)BNE    FLKNOT2⓪)JSR     IDfromTree⓪)MOVE    #rFwTyX,D5⓪)JMP     SyntaxErr⓪ FLKNOT2⓪ END⓪ END FLKNOT;⓪ ⓪ (*⓪!* PRUEFEN, OB noch LABELS undefiniert oder Forward-Typen übrig.⓪!*)⓪!⓪ PROCEDURE FinLblAndFwrd;⓪ BEGIN  ASSEMBLER⓪)LEA    FLKNOT,A5⓪)MOVE.L (A6),D2⓪)BEQ    EMPTY⓪)JMP    TravTr1⓪ !EMPTY⓪ END⓪ END FINLBLAndFwrd;⓪ ⓪ ⓪ (*⓪!*   Alle globalen Objekte in die Relozierliste eintragen.⓪!*)⓪ ⓪ VAR ImpOffset: LONGCARD;⓪$DataCodeOffs: LONGCARD;⓪$CurrDataOfs: LONGCARD;⓪ ⓪ PROCEDURE movReloc;⓪"BEGIN⓪$ASSEMBLER⓪);Relozierkette einer ID korrigieren⓪)MOVE.L  D1,D0⓪)SUB.L   D7,D0⓪)MOVE.L  D0,(A4)+       ;^letzte Ref. gleich mit ablegen⓪)BRA     relCont⓪ relNext  MOVE.L  D1,D0⓪)SUB.L   D7,D0⓪)MOVE.L  D0,(A0)⓪ relCont  LEA     0(A2,D1.L),A0  ;Adr. der vorigen Ref. nach A0⓪)MOVE.L  (A0),D1⓪)BNE     relNext⓪$END⓪"END movReloc;⓪ ⓪ PROCEDURE RelocData;⓪"BEGIN⓪$ASSEMBLER⓪)MOVE.L  DataStart,A0⓪)MOVE.L  DataCodeOffs,A3⓪)SUBA.L  CodeStart,A3   ;A3: Beginn v. DATA rel. zum Codebeginn⓪ lup20:   CMPA.L  DataPtr,A0⓪)BEQ     endOfD2⓪)MOVE.L  2(A0),D1      ;^letzte Ref.⓪)BEQ     ignore⓪)MOVE.L  A0,-(A7)⓪)JSR     movReloc      ;Relozierkette korrigieren & eintragen⓪)MOVE.L  (A7)+,A0⓪)MOVE.L  A3,D0         ;D0: Adr. der. Konst rel. zum Code-Beginn⓪)SUB.L   D7,D0         ;    ImportList-Korrektur⓪)MOVE.L  D0,(A4)+⓪)ADDA.W  (A0),A3⓪ ignore:  ADDA.W  (A0),A0⓪)ADDQ.L  #6,A0⓪)BRA     lup20⓪ endOfD2: MOVE.L  A3,CurrDataOfs  ; f. VPKNOT merken⓪$END⓪"END RelocData;⓪ ⓪ FORWARD VPKNOT;⓪ ⓪ PROCEDURE FINVAR;⓪ BEGIN⓪ ASSEMBLER⓪)MOVE.L  A2,-(A7)⓪)MOVE.L  A3,-(A7)⓪ ⓪)MOVE.L  options,D0⓪)BTST    #16,D0⓪)BEQ     hcr3          ;p- gesetzt: kein Protokoll⓪)TST.W   ProtFile⓪)BEQ     hcr3          ;ProtokollFile nicht offen⓪)JSR     ProtVarStart  ;Variablen ankündigen⓪ hcr3⓪)MOVE.L  Header,A2⓪)MOVE.L  22(A2),D3    ;OFFSET FUER VAR-ADRESSEN⓪);minus der Header-Länge (nun Codelänge):⓪)ADD.L   A2,D3⓪)SUB.L   CodeStart,D3⓪)⓪)MOVE.L  ImpOffset,D7⓪)⓪)JSR     RelocData      ;zuerst die Daten aus dem DATA-Puffer relozieren⓪)⓪)LEA     root(pc),A3    ;Root z. Verkett. d. Clienten f. d. Längenliste⓪)CLR.L   (A3)⓪)⓪)LEA     VPKNOT,A5⓪)MOVE.L  CodeStart,A2⓪)JSR     TravTr         ;IM GANZEN BAUM SUCHEN⓪)CLR.L   (A4)+⓪)⓪); Proc-Namen-Liste korrigieren, falls vorhanden⓪)TST.W   ProcNames⓪)BEQ     noName         ;Name ist nicht gefragt⓪)MOVE.L  6(A2),D0       ;^Body⓪ nxtLbl   LEA     -4(A2,D0.L),A0⓪)MOVE.L  (A0),D0⓪)BEQ     noName⓪)MOVE.L  D0,D1⓪)SUB.L   D7,D1⓪)MOVE.L  D1,(A0)⓪)BRA     nxtLbl⓪ noName⓪); Nun werden ExportListe & Programmcode verschoben (wg. gekürzter⓪); Importliste)⓪)⓪)MOVE.L  Header,A2⓪)MOVE.L  42(A2),A0      ;Codebeginn⓪)SUB.L   D7,42(A2)      ;  ...korrigiert⓪)MOVE.L  18(A2),D0      ;Exportliste⓪)BEQ     noExpLst⓪)MOVE.L  D0,A0⓪)SUB.L   D7,D0⓪)MOVE.L  D0,18(A2)      ;  ...korrigiert⓪ noExpLst ; A0 enthält nun Beginn des zu verschiebenden Bereichs⓪)ADDA.L  A2,A0⓪)MOVEM.L D0-D2/A0-A3,-(A7)⓪)MOVE.L  EvalStk,A3⓪)MOVE.L  A0,(A3)+       ;Source-Start⓪)MOVE.L  A4,D0⓪)SUB.L   A0,D0⓪)MOVE.L  D0,(A3)+       ;Anzahl⓪)SUBA.L  D7,A0⓪)MOVE.L  A0,(A3)+       ;Dest-Start⓪)JSR     Copy⓪)MOVEM.L (A7)+,D0-D2/A0-A3⓪ ⓪); Die restlichen Ptr korrigieren⓪)SUB.L   D7,6(A2)       ;^Body⓪)SUB.L   D7,10(A2)      ;^Modulende⓪)SUB.L   D7,22(A2)      ;^Relozierliste⓪)SUB.L   D7,62(A2)      ;^Data⓪)SUBA.L  D7,A4⓪ ⓪); Längenliste anlegen & gleich korrigeren⓪)⓪)MOVE.L  Header,A0      ;^Längenliste setzen⓪)MOVE.L  A4,D0⓪)SUB.L   A0,D0⓪)MOVE.L  D0,38(A0)⓪)⓪); zuerst die Längenliste für die Konstanten aus dem DATA-Puffer⓪)MOVE.L  DataStart,A0⓪)MOVE.L  DataCodeOffs,A3⓪)SUBA.L  CodeStart,A3   ;A3: Beginn v. DATA rel. zum Codebeginn⓪ lup20:   CMPA.L  DataPtr,A0⓪)BEQ     endOfD2⓪)MOVE.L  2(A0),D1      ;^letzte Ref.⓪)BEQ     ignore⓪)MOVE.L  A3,D0         ;D0: Adr. der. Konst rel. zum Code-Beginn⓪)SUB.L   D7,D0         ;    ImportList-Korrektur⓪)MOVE.L  D0,(A4)+⓪)MOVEQ   #0,D0⓪)MOVE.W  (A0),D0       ;Länge d. CONST⓪)MOVE.L  D0,(A4)+⓪)ADDA.W  D0,A3⓪ ignore:  ADDA.W  (A0),A0⓪)ADDQ.L  #6,A0⓪)BRA     lup20⓪ endOfD2:⓪)MOVE.L  root(pc),A0⓪)MOVE.L  A0,D0⓪)BEQ     empty⓪)⓪ cont     BCLR    #0,D0        ;ist es eine CONST?⓪)BNE     isConst⓪)MOVE.L  -8(A0),D0⓪)SUB.L   D7,D0        ;ImpOffset (Korrektur)⓪)MOVE.L  D0,(A4)+     ;Adresse⓪)MOVE.L  -4(A0),(A4)+ ;Länge⓪ cont2    MOVE.L  (A0),A0⓪)MOVE.L  A0,D0⓪)BNE     cont⓪)⓪ empty    MOVEQ   #0,D0⓪)MOVE.L  D0,(A4)+⓪)⓪)MOVEA.L (A7)+,A3⓪)MOVEA.L (A7)+,A2⓪)RTS⓪ ⓪); CONST in Längenliste aufnehmen geht anders:⓪ isConst  MOVE.L  D0,A0⓪)MOVE.L  8(A0),(A4)+    ;Adresse (bereits D7-korrigiert)⓪)MOVEQ   #0,D0⓪)MOVE.W  -2(A0),D0      ;Länge⓪)MOVE.L  D0,(A4)+⓪)BRA     cont2⓪ ⓪ root     DC.L    0⓪ END⓪ END FINVAR;⓪ ⓪ PROCEDURE VPKNOT;⓪ BEGIN⓪ ASSEMBLER⓪);D3: Länge des Codes, Offset der glob. Vars⓪);D7: Korrektur-Offset der Importliste⓪)⓪)BSET    #5,-10(A1,D2.L) ;IMPORTIERT?⓪)BNE     ok              ;dann nicht⓪)⓪)CMP.B   #15,D0        ;MODULE?⓪)BEQ     VPKNOT1⓪)CMP.B   #6,D0         ;PROC?⓪)BNE.W   VPKNOT3⓪)⓪); Procedure⓪)⓪)MOVE.L  -14(A1,D2.L),D5   ;Adr⓪)BEQ     noImpl            ;Implementation fehlt⓪)MOVE.L  -26(A1,D2.L),D1   ;^letzte Ref⓪)BEQ     noRef             ;keine Referenz⓪)JSR     movReloc⓪)SUB.L   D7,D5⓪)MOVE.L  D5,(A4)+⓪ noRef    LEA     -26(A1,D2.L),A0   ;Pointerkette für Längenliste aufbauen⓪)MOVE.L  A0,(A3)⓪)MOVE.L  A0,A3⓪)CLR.L   (A3)⓪ ok       RTS⓪ ⓪ noImpl   JSR     IDfromTree⓪)BTST    #4,-10(A1,D2.L)    ;exportiert?⓪)BEQ     noExp⓪)MOVE    #rPrIpl,D5⓪)BRA     isExp⓪ noExp    MOVE    #rUnFw,D5⓪ isExp    JMP     SyntaxErr⓪)⓪); Module⓪)⓪ VPKNOT1  MOVE.L  -30(A1,D2.L),D1   ;^letzte Ref⓪)BEQ     noRef2            ;keine Referenz: nicht in RelocListe⓪)JSR     movReloc⓪)MOVE.L  -18(A1,D2.L),D0   ;Adr⓪)SUB.L   D7,D0⓪)MOVE.L  D0,(A4)+⓪ noRef2   LEA     -30(A1,D2.L),A0   ;Pointerkette für Längenliste aufbauen⓪)MOVE.L  A0,(A3)⓪)MOVE.L  A0,A3⓪)CLR.L   (A3)⓪)RTS⓪)⓪ VPKNOT3  CMP.B   #17,D0⓪)BNE     VPKNOT4⓪)⓪); Variable⓪)⓪)MOVE.L  -22(A1,D2.L),D1 ; letzte Ref.⓪)BEQ     ok⓪)JSR     movReloc⓪)MOVE.L  -14(A1,D2.L),D0 ; Adr.⓪)ADD.L   D3,D0         ;VAR-OFFSET DAZU⓪)SUB.L   D7,D0         ;ImportList-Korrektur⓪)MOVE.L  D0,(A4)+⓪)⓪); Variable ggf. protokollieren⓪)⓪)MOVE.L  options,D0⓪)BTST    #16,D0⓪)BEQ     hcr3          ;p- gesetzt: kein Protokoll⓪)TST.W   ProtFile⓪)BEQ     hcr3          ;ProtokollFile nicht offen⓪)JSR     ProtVar       ;Variablenname/Adresse ins Protokollfile⓪ hcr3     RTS⓪ ⓪ !VPKNOT4 CMP.B   #28,D0        ;TABLE im Code-Segment⓪)BNE     VPKNOT5⓪)MOVE.L  -18(A1,D2.L),D1⓪)BEQ     noRef3⓪)JSR     movReloc⓪)MOVE.L  -14(A1,D2.L),D0⓪)SUB.L   D7,D0⓪)MOVE.L  D0,(A4)+⓪ noRef3   LEA     -18(A1,D2.L),A0   ;Pointerkette für Längenliste aufbauen⓪)MOVE.L  A0,(A3)⓪)MOVE.L  A0,A3⓪)CLR.L   (A3)⓪)RTS⓪ ⓪ VPKNOT5  CMP.B   #50,D0        ;CONST hinter Code-Segment⓪)BNE     VPKNOT2⓪)BCLR    #2,-8-2(A1,D2.L)⓪)BEQ     hcr3           ; -> bereits bearbeitet oder unbenutzt⓪); dieses Datum wurde in den Code kopiert⓪)MOVE.L  CurrDataOfs,D0 ;D0: Adr. der. Konst rel. zum Code-Beginn⓪)MOVE.L  D0,A0⓪)SUB.L   D7,D0          ;    ImportList-Korrektur⓪)MOVE.L  D0,-8-6(A1,D2.L) ;Adr. merken (f. FINVAR & FINEXP)⓪); Offset zum nächsten Datum im Code bestimmen:⓪)ADDA.W  -8-16(A1,D2.L),A0 ;echte Länge im DATA-Segment aufaddieren⓪)MOVE.L  A0,CurrDataOfs⓪); Relozierkette aufbauen⓪)MOVE.L  -8-14(A1,D2.L),D1 ;^letzte Ref⓪)BEQ     ignore         ;unbenutzt? (dann wird sie aber exportiert)⓪)JSR     movReloc       ;Relozierkette korrigieren & eintragen⓪)MOVE.L  -8-6(A1,D2.L),(A4)+⓪ ignore   ;Pointerkette für Längenliste aufbauen⓪);bei Consts geht das so: Die Verkettung geschieht über den⓪); "^letzte Ref" im Tree.⓪); So findet FINVAR am Ende zum Aufbau der Längenliste die Ptr⓪); als Zeiger auf ein Längen-Word und eine Long-Adr.⓪); Um dies von den Procs/Tables usw. zu unterscheiden, bei denen⓪); der Ptr auf ein Längen-Long und ein Adr-Long zeigt,⓪); wird das Bit 0 des Ptrs gesetzt.⓪)LEA     -8-14(A1,D2.L),A0   ;A0: Adr. des nicht mehr benutzten ^Ref⓪)ADDQ.L  #1,A0               ;als CONST markieren⓪)MOVE.L  A0,(A3)⓪)SUBQ.L  #1,A0⓪)MOVE.L  A0,A3⓪)CLR.L   (A3)⓪ ⓪ VPKNOT2:⓪ END⓪ END VPKNOT;⓪ ⓪ ⓪ (*⓪$Relozierliste der importierten Vars, Procs & Consts nacharbeiten.⓪$⓪$In den Einträgen für die Adr. von importierten Vars/Procs/Consts zeigt⓪$ein Ptr auf die Stelle in der Importliste, wo der Ptr auf die⓪$letzte Ref. des Items einzutragen ist. Dies wird hier getan.⓪$⓪$Außerdem wird die Importliste so gekürzt, daß nur noch die⓪$wirklich benutzten Vars/Procs/Consts drin stehen.⓪ *)⓪ ⓪ FORWARD FIKNOT;⓪ ⓪ PROCEDURE FinImp;⓪ BEGIN⓪ ASSEMBLER⓪); Zuerst die Ptr eintragen⓪)MOVE.L  A2,-(A7)⓪)MOVE.L  Header,A2⓪)ADDA.L  14(A2),A2      ;^Importliste⓪)LEA     FIKNOT,A5⓪)JSR     TravTr         ; scannen des Relocation Stack⓪@; ist hier eigentlich überflüssig⓪)⓪); Nun die Importliste kürzen; dazu alle Null-Einträge löschen⓪)MOVE.L  Header,A2⓪)ADDA.L  14(A2),A2      ;^Importliste⓪)MOVE.L  A2,A0          ; A2: Source-, A0: Dest-Pointer⓪)⓪ nextkey  MOVE.L  (A2)+,(A0)+    ;Key⓪)BEQ     ende           ;ende der Importlisten⓪ ImpRest4 MOVE.W  (A2)+,D0       ;Namen kopieren⓪)MOVE.W  D0,(A0)+⓪)CMP.B   #$FE,D0⓪)BCS     ImpRest4⓪ next     MOVE.W  (A2)+,(A0)+    ;ItemNr kopieren⓪)BEQ     nextkey        ;Ende dieser Liste⓪)MOVE.L  (A2)+,D0       ;Ref-Ptr⓪)BEQ     delet          ;Ist Null: löschen⓪)MOVE.L  D0,(A0)+       ;Referenz-Ptr kopieren⓪)BRA     next⓪ delet    SUBQ.L  #2,A0          ;ItemNr wieder weg⓪)BRA     next⓪ ⓪ ende     MOVE.L  A2,D3⓪)SUB.L   A0,D3          ;D3 enthält nun Diff. zur neuen Länge (positiv)⓪)MOVE.L  D3,ImpOffset   ;merken f. FINVAR⓪ ⓪); die Proc-, Modul-, Table- und Var-Verkettungen werden⓪); später in FINVAR korrigiert, ebenso die Längenliste⓪); Auch das Verschieben und die Korrektur der Ptr im Header⓪); kommt erst später.⓪)⓪); Importliste korrigieren⓪)MOVE.L  Header,A2⓪)ADDA.L  14(A2),A2      ;^Importliste⓪)MOVE.L  CodeStart,A5⓪)⓪ nextkey2 TST.L   (A2)+          ;Key⓪)BEQ     ende2          ;ende der Importlisten⓪ ImpRest2 MOVE.W  (A2)+,D0       ;Namen überspringen⓪)CMP.B   #$FE,D0⓪)BCS     ImpRest2⓪ next2    TST.W   (A2)+          ;ItemNr⓪)BEQ     nextkey2       ;Ende dieser Liste⓪);Relozierkette korrigieren⓪)MOVE.L  (A2),D1⓪)MOVE.L  D1,D0⓪)SUB.L   D3,D0⓪)MOVE.L  D0,(A2)+⓪)BRA     relCont⓪ relNext  MOVE.L  D1,D0⓪)SUB.L   D3,D0⓪)MOVE.L  D0,(A0)⓪ relCont  LEA     0(A5,D1.L),A0  ;Adr. der vorigen Ref. nach A0⓪)MOVE.L  (A0),D1⓪)BNE     relNext⓪)BRA     next2⓪ ende2⓪)MOVE.L  (A7)+,A2⓪ END⓪ END FinImp;⓪ ⓪ PROCEDURE FIKNOT;⓪ BEGIN⓪ ASSEMBLER⓪)BTST    #13,D0        ;NUR IMPORTIERTE IDS⓪)BEQ     FIKNOT1⓪)CMPI.B  #6,D0         ;PROC?⓪)BEQ     FIKNOT2⓪)CMPI.B  #50,D0        ;CONST?⓪)BEQ     FIKNOT5⓪)CMPI.B  #17,D0        ;VAR?⓪)BNE     FIKNOT1⓪ FIKNOT4  MOVE.L  -14-8(A1,D2.L),D1 ;LETZTE REF BEI VAR⓪)BRA     FIKNOT3⓪ FIKNOT5  MOVE.L  -14-8(A1,D2.L),D1 ;LETZTE REF BEI CONST⓪)BRA     FIKNOT3⓪ FIKNOT2  MOVE.L  -18-8(A1,D2.L),D1 ;LETZTE REF BEI PROC⓪ FIKNOT3  MOVE.L  -06-8(A1,D2.L),D0 ;^IMPORTLISTE (statt Adr.)⓪)MOVE.L  D1,0(A2,D0.L)  ;EINTRAGEN⓪ FIKNOT1⓪ END⓪ END FIKNOT;⓪ ⓪ ⓪ (*⓪!*   EXPORTLISTE NACHARBEITEN⓪!*)⓪ ⓪ PROCEDURE FinExp;⓪ BEGIN⓪ ASSEMBLER⓪); Die Importlist-Korrekturen wurden bei den eigenen IDs⓪); zwar schon schon in FINVar vorgenommen, jedoch nur bei⓪); den abgelegten Werten für die Reloc-List, usw, jedoch⓪); wurden die Original-Einträge bei den IDs nicht korrigiert.⓪); Deshalb jetzt nochmal.⓪)MOVE.L  Header,A0⓪)MOVE.L  18(A0),D0⓪)BEQ     FinExp2       ;KEINE EXPORTS⓪)MOVE.L  22(A0),D2     ;OFFSET AUF GLOB.VAR⓪);minus der Header-Länge (nun Codelänge):⓪)ADD.L   A0,D2⓪)SUB.L   CodeStart,D2⓪)ADDA.L  D0,A0         ;ABS. ^EXPORTLISTE⓪)MOVE.L  ImpOffset,D7⓪ FinExp1  TST.W   (A0)+⓪)BEQ     FinExp2       ;FERTIG⓪)MOVE.L  (A0),D1       ;^ID-Beschreibung⓪)CMPI.B  #17,-1(A1,D1.L) ;VAR?⓪)BEQ     FinExp3⓪)CMPI.B  #50,-1(A1,D1.L) ;CONST?⓪)BEQ     FinExp5⓪); Proc⓪)MOVE.L  -6(A1,D1.L),D0⓪)SUB.L   D7,D0⓪)MOVE.L  D0,(A0)+      ;REL.PROC-ADR stattdessen eintragen⓪)BRA     FinExp1⓪ FinExp3  ; Var⓪)MOVE.L  -6(A1,D1.L),D0 ;alt: Adr. der Var (Offset ab Null)⓪)ADD.L   D2,D0⓪); ImpOffset ist hier bereits durch 22(A0) korrigiert⓪)MOVE.L  D0,(A0)+       ;neu: Adr. der Var (Offset ab Codelänge)⓪)BRA     FinExp1⓪ FinExp5  ; Const⓪)MOVE.L  -6(A1,D1.L),D0 ; ADR d. Const (bereits D7-korrigiert)⓪)MOVE.L  D0,(A0)+      ;REL.CONST-ADR stattdessen eintragen⓪)BRA     FinExp1⓪ FinExp2⓪(END⓪ END FinExp;⓪ ⓪ (*⓪ *   ----------------------------------⓪ *   Alle Referenzen auf einen Opaque-Typ umhängen,⓪ *      wenn dieser nachdeklariert wurde.⓪ *   ----------------------------------⓪ *⓪ *      (D0,D2)⓪ *⓪ *      D2 = rel. ^Beschreibung im ID-Baum + 10⓪ *      D1 = zu suchender Opaque-Pointer (der Eintrag ist bereits in⓪ *            Relay auf richtigen Typ umgewandelt)⓪ *      D0 = Objekt-Kennung.⓪ ⓪'Da TreSrc keine anonymen Einträge erreicht, müssen mögliche⓪'Verweise auf anonyme Einträge von OpqKnot gefunden und verfolgt⓪'werden. Dies sind just die Pointer, die auch direkt auf Opaques⓪'zeigen können - mit Ausnahme der Prozedur- und Parameter-Deskriptoren:⓪'dort zeigen die ^nächsten Parameter evtl. auf anonyme Verwendungen⓪'des Opaques, die ^Typen können EBENFALLS auf anonyme Verwendung⓪'zeigen, nämlich in Open Arrays!⓪'⓪'Beim Verfolgen von POINTER TO RECORD-Strukturen und bei Prozedurtypen⓪'können Endlosschleifen auftreten. Diese werden vermieden durch⓪'Markieren der bearbeiteten Pointer-Einträge in Bit 2 des⓪'Kennungsbytes ("Typ-Eintrag").⓪'⓪'Um die Markierungen anschließend wieder löschen zu können, werden⓪'die markierten Einträge durch eine Pointerkette verbunden. Diese⓪'schreiben wir (ähem) anstelle der Längenangaben (immer 4) in den⓪'Baum.⓪ *)⓪ FORWARD TravTr2;⓪ ⓪ PROCEDURE OpqKnot;⓪ BEGIN⓪ ASSEMBLER⓪ CopInf0  CMP.B   #13,D0       ;Record?⓪)BNE     CopInf5⓪)⓪); lokalen Baum eines Records scannen⓪)⓪)MOVE.L  -22(A1,D2.L),D2 ;^lokalen Baum⓪)BEQ     CopInf9         ;wenn leer, dann RTS⓪)JMP     TravTr2         ;durchsuchen⓪)⓪); Pointer: Bearbeitung markieren⓪)⓪ CopInf5  CMP.B   #19,D0       ;PROCEDURE ?⓪)BEQ     CopInf10⓪)CMP.B   #20,D0       ;POINTER ?⓪)BNE     CopInf8⓪ CopInf10 BCLR    #2,-10(A1,D2.L) ;markieren⓪)BEQ     CopInf9         ;war schon fertig⓪)MOVE.L  D4,-14(A1,D2.L) ;neue Markierung: in Pointerkette⓪)MOVE.L  D2,D4⓪)⓪); Beschreibung des Objektes suchen⓪)⓪ CopInf8  LEA     OpqUsers(pc),A0 ;Liste mit Item-Beschreibung⓪ CopInf3  CMP.B   (A0)+,D0⓪)BEQ     CopInf4      ;gefunden⓪)ADDQ.L  #3,A0⓪)TST.B   (A0)         ;Ende der Liste?⓪)BNE     CopInf3      ; nein⓪ CopInf9  RTS⓪)⓪ CopInf4  CLR.L   D0⓪)MOVE.B  (A0)+,D0     ;Pointer-Offset in Beschreibung⓪)SUB.L   D2,D0⓪)NEG.L   D0⓪)CMP.L   -8(A1,D0.L),D1 ;^unseren Opaque-Kandidaten ?⓪)BNE     CopInf1        ;  nein⓪)⓪); Opaque gefunden⓪)MOVE.L  -6(A1,D1.L),-8(A1,D0.L) ;neue Adr aus Relay drüberschreiben⓪)BSR.S   CopInf2        ;weitere User prüfen⓪)TST.B   (A0)           ;Offset zum ^mögl. anonymen Opq-User...⓪)BEQ     CopInf9        ;  den haben wir schon behandelt⓪)BRA     CopInf7⓪ ⓪ CopInf1  BSR.S   CopInf2        ;weitere User prüfen⓪ CopInf7  ;^anonymen Opq-User prüfen⓪)CLR.L   D2⓪)MOVE.B  (A0),D2        ;^mögl. anonymen Opq-User⓪)ADD.L   D2,D0⓪)MOVE.L  -8(A1,D0.L),D2 ;neuer ^⓪)BEQ     CopInf9⓪)MOVE.W  -2(A1,D2.L),D0 ;zugeh. Kennung⓪)ADDQ.L  #8,D2          ;üblicher Offset in TreSrc⓪)BRA     CopInf0⓪ ⓪ CopInf2  MOVEM.L A0/D0/D2,-(A7)⓪)TST.B   1(A0)⓪)BEQ     CopInf6⓪); es gibt einen zweiten mögl. ^Opq-User⓪)CLR.L   D2⓪)MOVE.B  1(A0),D2⓪)ADD.L   D2,D0⓪)MOVE.L  -8(A1,D0.L),D2 ;neuer ^⓪)BEQ     CopInf6⓪)MOVE.W  -2(A1,D2.L),D0 ;zugeh. Kennung⓪)ADDQ.L  #8,D2          ;üblicher Offset in TreSrc⓪)BSR     CopInf0⓪ CopInf6  MOVEM.L (A7)+,A0/D0/D2⓪)RTS⓪ ⓪); Tabelle: ItemNr, Offset zu ^möglichen Opaquetyp,⓪);          Offset von dort zu mögl ^anonymen Opaque-User⓪)⓪ OpqUsers DC.B     6, 14, 4, 0  ;Procedure⓪)DC.B     7, 10, 0, 4  ;Proc.Parameter⓪)DC.B    12, 14, 0, 0  ;Array⓪)DC.B    14, 10, 0, 0  ;Recordfeld⓪)DC.B    17, 10, 0, 0  ;Var⓪)DC.B    18,  6, 0, 0  ;Konstante alt⓪)DC.B    19, 14, 4, 0  ;ProcType⓪)DC.B    20, 10, 0, 0  ;Pointer⓪)DC.B    32,  6, 0, 0  ;Open Array⓪)DC.B    42,  6, 0, 0  ;Long Open Array⓪)DC.B    44, 10, 0, 0  ;ProcType f. lok. Procs⓪)DC.B    50, 10, 0, 0  ;Konstante neu⓪)DC.B     0⓪)SYNC⓪!END⓪ END OpqKnot;⓪ ⓪ (*⓪(speziell für opqKnot:⓪(wie TravTr1, jedoch wird bei Verfolgen eines Relays geprüft,⓪(ob der Verweis direkt auf (A1,D1.L) zeigt (alter Opaque-Eintrag).⓪(⓪(D4 ist zu erhalten (enthält Wurzel der Pointerkette, die die⓪(markierten Einträge verbindet)!⓪!*)⓪ ⓪ PROCEDURE TravTr2;⓪ BEGIN⓪ ASSEMBLER⓪ TravTr1L MOVE.L  D2,-(A7)⓪)MOVE.L  -4(A1,D2.L),D2 ;LINKEN AST VERFOLGEN⓪)BEQ     TravTr2L⓪)BSR     TravTr1L⓪ TravTr2L MOVE.L  (A7),D2⓪)MOVE.L  -8(A1,D2.L),D2 ;RECHTEN AST VERFOLGEN⓪)BEQ     TravTr4⓪)BSR     TravTr1L⓪ TravTr4  MOVE.L  (A7)+,D2⓪ ⓪ TravTr5  SUBQ.L  #2,D2          ;ID WEG⓪)CMPI.W  #$FE00,-8(A1,D2.L)⓪)BCS     TravTr5        ;noch keine Endmarke⓪)⓪)MOVE.W  -10(A1,D2.L),D0 ;KENNUNG⓪)TST.B   D0⓪)BNE     TravTr7        ;KEIN RELAY⓪)MOVE.L  -14(A1,D2.L),D0⓪)⓪); Eintrag ist Relay⓪)⓪)CMP.L   D1,D0          ;Verweis auf alten Opaque-Typ?⓪)BNE     TravTr8⓪)MOVE.L  -6(A1,D1.L),D0 ;durch Nachdekl. ersetzen⓪)MOVE.L  D0,-14(A1,D2.L)⓪ TravTr8  MOVE.L  D0,D2⓪)ADDQ.L  #8,D2          ;üblichen Offset wiederherstellen⓪)MOVE.W  -10(A1,D2.L),D0⓪ ⓪ TravTr7  CMPI.B  #15,D0        ;lokales Modul?⓪)BEQ     L3⓪)CMPI.B  #16,D0        ;QUALIFIER?⓪)BNE     L2⓪ L3       MOVEM.L D0/D2,-(A7)⓪)MOVE.L  -14(A1,D2.L),D2⓪)BEQ     L4            ;Unterbaum ist leer⓪)JSR     TravTr2       ;UNTERBAUM DURCHSUCHEN⓪ L4       MOVEM.L (A7)+,D0/D2⓪ L2       JMP     OpqKnot⓪ TravTr6⓪ END⓪ END TravTr2;⓪ ⓪ (* Bei Nachdeklaration eines Opaques Änderung aller bestehenden⓪#Referenzen im globalen Scope veranlassen.⓪#⓪#Das globale Scope muß das oberste auf dem Display Stack sein,⓪#weil nur dort die Nachdeklaration erfolgen kann!⓪#⓪#D1 = zu suchender Opaque-Pointer⓪((der Eintrag ist bereits in Relay auf richtigen Typ umgewandelt)⓪ *)⓪ ⓪ PROCEDURE NewOpaque;⓪ ⓪ BEGIN⓪"ASSEMBLER⓪)MOVE.L  (A6),D2       ;globales Level⓪)BEQ     opq1          ; ist leer⓪)CLR.L   D4            ;Wurzel der Markierungs-Pointerkette⓪)JSR     TravTr2⓪)⓪); markierte Typeinträge reparieren⓪)⓪)TST.L   D4⓪)BEQ     opq1          ;gar kein Eintrag in der Kette⓪)MOVEQ   #4,D0⓪#opq2  MOVE.L  -14(A1,D4.L),D2⓪)MOVE.L  D0,-14(A1,D4.L) ;korrekte Typlänge eintragen⓪)BSET    #2,-10(A1,D4.L) ;wieder als Typ markieren⓪)MOVE.L  D2,D4⓪)BNE     opq2          ; mehr Kettenglieder?⓪)⓪#opq1⓪"END⓪ END NewOpaque;⓪ ⓪ ⓪ (* in lokalen Scopes nach nicht-implementierten⓪#FORWARD-Deklarationen suchen⓪ *)⓪ ⓪ PROCEDURE FwdKnot;⓪ ⓪ BEGIN⓪"ASSEMBLER⓪)CMP.B   #6,D0             ;Procedure?⓪)BNE     done⓪)TST.L   -14(A1,D2.L)⓪)BNE     done              ;Adresse eingetragen⓪)JSR     IDfromTree⓪)MOVE    #rUnFw,D5⓪)JMP     SyntaxErr⓪ done⓪"END⓪ END FwdKnot;⓪ ⓪ ⓪ PROCEDURE MovParA3Knot; (* /D0/ *)⓪"(* Für Parms auf A3 (Vars sind hier noch nicht deklariert) *)⓪"BEGIN⓪$ASSEMBLER⓪(CMPI.B  #17,D0⓪(BNE     noVar⓪(MOVE.L  -8-6(A1,D2.L),D0        ;Offset der Variablen zu A6⓪(BMI     error                   ;muß erstmal positiv sein⓪(CMPI.W  #1,GLOBAL               ;lokale Proc?⓪(BEQ     isGlobal⓪(SUBQ.L  #4,D0                   ;dann Offset f. Stat Link abziehen⓪(BCS     error⓪&isGlobal⓪(SUB.L   ParAdr,D0               ;Offset um Parm-Länge runterschieben⓪(BCC     error⓪(MOVE.L  D0,-8-6(A1,D2.L)⓪&noVar⓪(RTS⓪&error⓪(TRAP    #6⓪(DC.W    -112          ;um internen Fehler zu melden⓪$END⓪"END MovParA3Knot;⓪ ⓪ PROCEDURE MovParA7Knot; (* /D0/ *)⓪"(*⓪#* Für Parms auf A7 (Vars sind hier noch nicht deklariert):⓪#* Die Parameter müssen so erhöht werden, daß sie A5-relativ ansprechbar⓪#* sind. Da der Static Link mit verschoben wird, muß lediglich immer⓪#* 8 addiert werden.⓪#*)⓪"BEGIN⓪$ASSEMBLER⓪(CMPI.B  #17,D0⓪(BNE     noVar⓪(; Parm-Start berechnen in D4⓪(ADDQ.L  #8,-8-6(A1,D2.L)⓪&noVar⓪(RTS⓪&error⓪(TRAP    #6⓪(DC.W    -113          ;um internen Fehler zu melden⓪$END⓪"END MovParA7Knot;⓪ ⓪ PROCEDURE ScanForName;⓪"BEGIN⓪$ASSEMBLER⓪(TST.L   D1⓪(BNE     cont⓪(CMP.L   D3,D2⓪(BEQ     found⓪(MOVE.L  D4,D2          ;und bei Relays auch diesen Eintrag prüfen⓪ TravTr5 SUBQ.L  #2,D2          ;ID WEG⓪(CMPI.W  #$FE00,-8(A1,D2.L)⓪(BCS     TravTr5        ;noch keine Endmarke⓪(CMP.L   D3,D2⓪(BNE     cont⓪&found⓪(; gefunden?⓪(CMPI.B  #$FE,-9(A1,D4.L) ; ist Name anonym?⓪(BCC     cont             ; dann weitersuchen⓪(MOVE.L  D4,D1⓪&cont⓪$END⓪"END ScanForName;⓪ ⓪ (*⓪!* Findet den Namen eines Idents im Baum, auch von Relays.⓪!*   /D0,D4/⓪!* IN:⓪!*   (A1,D2.L): Ptr auf Ende der ID-Beschreibung⓪!* OUT:⓪!*   (A1,D4.L): Ptr vor Beginn des Namens (steht rückwärts im Speicher!),⓪!*              D4 ist Null, wenn ID nicht gefunden⓪!*)⓪ PROCEDURE GetNameOfId;⓪"BEGIN⓪$ASSEMBLER⓪(MOVEM.L D1-D3/A0/A5,-(A7)⓪(MOVE.L  D2,D3⓪(ADDQ.L  #8,D3⓪(MOVEQ   #0,D1⓪(LEA     ScanForName,A5⓪(JSR     TravTr⓪(TST.L   D1⓪(BEQ     notfound⓪(SUBQ.L  #8,D1⓪¬found⓪(MOVE.L  D1,D4⓪(MOVEM.L (A7)+,D1-D3/A0/A5⓪$END⓪"END GetNameOfId;⓪ ⓪ ⓪ FORWARD VerifyTree;⓪ ⓪ PROCEDURE VerifyItem;⓪ BEGIN⓪ ASSEMBLER⓪);D2: ^Eintrag, D0: Kennung⓪)CMPI.B  #31,D0⓪)BEQ     CopInf4      ;String Const ignorieren⓪)SUBQ.L  #2,D2⓪)LEA     ITEMS,A0     ;Liste mit Item-Beschreibung⓪)MOVE.B  (A0)+,D1⓪ CopInf30 CMP.B   D1,D0⓪)BEQ     CopInf1      ;gefunden⓪ CopInf20 TST.B   (A0)+        ;nicht gefunden: Ende des Eintrags suchen⓪)BNE     CopInf20⓪)MOVE.B  (A0)+,D1     ;Ende der Liste?⓪)BNE     CopInf30     ; nein⓪ ⓪ error    JSR     IDfromTree⓪)MOVE    #rTree,D5    ; ja, exp. Item ist nicht definiert⓪)JMP     SyntaxErr⓪ ⓪); Ende der Beschreibung des Items⓪ CopInf4  RTS⓪ ⓪ CopInf1  MOVE.B  (A0)+,D0     ;Beschreibung kopieren⓪)BEQ     CopInf4      ;fertig⓪)CMPI.B  #1,D0        ;Ptr?⓪)BEQ     CopInf10⓪)CMPI.B  #2,D0        ;Const.L?⓪)BEQ     CopInf2⓪)CMPI.B  #3,D0        ;Const.W?⓪)BEQ     CopInf3⓪)CMPI.B  #4,D0        ;Unterbaum?⓪)BEQ     CopInf7⓪)CMPI.B  #5,D0        ;^ID? (auf 1. Enum-Elem), geht wie Ptr⓪)BEQ     CopInf10⓪)CMPI.B  #7,D0        ;Insert? -> ignorieren⓪)BEQ     CopInf17⓪)CMPI.B  #8,D0        ;^ID? (Enum-Elem-Kette), geht wie Ptr⓪)BEQ     CopInf10⓪)BRA     CopInf4      ;sonst ists eh zu ende⓪ ⓪ CopInf17 MOVEQ   #0,D0⓪)MOVE.B  (A0)+,D0⓪)SUB.L   D0,D2⓪)BRA     CopInf1⓪ ⓪ CopInf2  SUBQ.L  #4,D2⓪)BRA     CopInf1⓪ ⓪ CopInf3  SUBQ.L  #2,D2⓪)BRA     CopInf1⓪ ⓪ CopInf7  ; Unterbaum prüfen⓪)SUBQ.L  #4,D2⓪)MOVEM.L A0/D2,-(A7)⓪)MOVE.L  0(A1,D2.L),D2⓪)BEQ     CopInf8      ;Unterbaum ist leer⓪)CMP.L   D3,D2  ; durch unsigned Test werden auch pos. Werte erkannt⓪)BCS     error⓪)JSR     VerifyTree⓪ CopInf8  MOVEM.L (A7)+,A0/D2⓪)BRA     CopInf1⓪ ⓪ CopInf10 ; Pointer und ID prüfen⓪)SUBQ.L  #4,D2⓪)MOVE.L  0(A1,D2.L),D1⓪)BEQ     CopInf1⓪)CMP.L   D3,D1  ; durch unsigned Test werden auch pos. Werte erkannt⓪)BCC     CopInf1⓪)BRA     error⓪"END⓪ END VerifyItem;⓪ ⓪ PROCEDURE VerifyKnot;⓪"BEGIN⓪$ASSEMBLER⓪)CMP.L   D3,D4⓪)BCS     error  ; durch unsigned Test werden auch pos. Werte erkannt⓪)CMP.L   D3,D2⓪)BCS     error  ; durch unsigned Test werden auch pos. Werte erkannt⓪)SUBQ.L  #8,D2⓪)JMP     VerifyItem⓪'error⓪)JSR     IDfromTree⓪)MOVE.W  #rTree,D5⓪)JMP     SyntaxErr⓪$END⓪"END VerifyKnot;⓪ ⓪ PROCEDURE VerifyTree;⓪"BEGIN⓪$ASSEMBLER⓪); Lokalen Baum prüfen. Adr in D2; Untergrenze in D3⓪)LEA     VerifyKnot,A5⓪)JSR     TravTr1⓪$END⓪"END VerifyTree;⓪ ⓪ PROCEDURE VerifyWholeTree;⓪"BEGIN⓪$ASSEMBLER⓪); Ganzen Baum prüfen.⓪)MOVE.L  TreSpc,D3⓪)LEA     VerifyKnot,A5⓪ next     MOVE.L  (A6)+,D2      ;GLOBAL LEVEL⓪)BMI     TravTr8⓪)BEQ     next⓪)BRA     TravTr9⓪ TravTr8  JSR     TravTr1⓪)BRA     next⓪ TravTr9  JMP     TravTr0⓪$END⓪"END VerifyWholeTree;⓪ ⓪ ⓪ PROCEDURE FCKNOT;⓪ BEGIN  ASSEMBLER⓪)CMPI.B  #50,D0         ; CONST (neu)⓪)BNE     FLKNOT3⓪)BTST    #8+4,D0        ; exportiert?⓪)BNE     useData        ;   ja -> in DATA ablegen⓪)BTST    #8+5,D0        ; importiert?⓪)BNE     FLKNOT3        ;   ja -> ignorieren⓪)TST.L   -8-14(A1,D2.L) ;^letzte Ref⓪)BEQ     FLKNOT3        ;   Null -> ignorieren⓪); umkopieren in DATA-Puffer⓪ useData  MOVE.L  DataPtr,A0⓪)MOVE.W  -8-16(A1,D2.L),D0 ;BYTELAENGE⓪)ADDQ    #1,D0⓪)BCLR    #0,D0⓪)MOVE.W  D0,(A0)+             ;Größe d. Konst⓪)MOVE.L  -8-14(A1,D2.L),(A0)+  ;^letzte Ref⓪)TST.W   D0⓪)BEQ     add0w⓪)MOVE.L  D2,-(A7)⓪ ConsID3b MOVE.L  -8-20(A1,D2.L),(A0)+ ;KONSTANTE AUS BAUM KOPIEREN⓪)SUBQ.L  #4,D2⓪)SUBQ.W  #4,D0⓪)BGT     ConsID3b⓪)BEQ     ok2⓪); es sind 2 Byte zuviel kopiert worden⓪)SUBQ.L  #2,A0⓪ ok2:     MOVE.L  (A7)+,D2⓪); Strings im DATA müssen immer 0-terminiert werden:⓪ add0w:   MOVE.L  -8-10(A1,D2.L),D0 ;Typ⓪)CMP.L   StrPtr,D0⓪)BNE     notStrng⓪)MOVE.W  -8-16(A1,D2.L),D0 ;BYTELAENGE⓪)BEQ     add0w2⓪)BTST    #0,D0⓪)BEQ     isEven⓪); wenn String ungerade Länge hat, einfach letztes Byte löschen⓪)CLR.B   -1(A0)⓪)BRA     notStrng⓪ FLKNOT3: RTS⓪ isEven   ; bei gerader Länge: prüfen, ob 0C am Ende, sonst eins anfügen⓪)TST.B   -1(A0)⓪)BEQ     notStrng⓪ add0w2:  MOVE.L  A0,-(A7)⓪)MOVE.L  DataPtr,A0⓪)ADDQ.W  #2,(A0)        ; Länge des Datums im DATA-Puffer um 2 erhöhen⓪)MOVE.L  (A7)+,A0⓪)CLR.W   (A0)+⓪ notStrng MOVE.L  A0,DataPtr⓪)CMPA.L  DataEnd,A0⓪)BLS     ok⓪)MOVE    #rDaSpc,D5     ; DATA-Puffer übergelaufen⓪)JMP     SyntaxErr⓪ ok:⓪ END⓪ END FCKNOT;⓪ ⓪ (*⓪!* Die benutzten nicht-importierten CONSTS in den Data-Puffer umtragen⓪!* (wird nur für lokale Levels benutzt - globales wird direkt am Ende⓪!* ohne Umweg über DATA-Puffer an den Code angehängt, damit Speicherplatz⓪!* nicht so sehr verschwendet wird).⓪!*)⓪ ⓪ PROCEDURE FinConst;⓪ BEGIN  ASSEMBLER⓪)LEA    FCKNOT,A5⓪)MOVE.L (A6),D2⓪)BEQ    EMPTY⓪)JMP    TravTr1⓪ !EMPTY⓪ END⓪ END FINConst;⓪ ⓪ (*⓪!* Alle Konstanten aus dem DATA-Puffer hinter den Code (A4)⓪!* kopieren und dann Offsets f. Relozierliste festlegen.⓪!* Die Offsets werden, ebenso wie die der Vars, relativ zum Codebeginn⓪!* berechnet. So braucht dann beim Relozieren im Loader keine Fallunter-⓪!* scheidung zw. Code, DATA und Vars gemacht werden. Nur der Linker muß das⓪!* tun, weshalb er dazu im Modulheader die Grenze zw. Code und DATA erhält.⓪!* Das Ganze geschieht in 2 Routinen: Zuerst kopiert FinishData die Daten⓪!* vom Puffer hinter den Code, dann erzeugt RelocData die Relozierliste.⓪!*⓪!* Zusätzlich werden auch die benamten Konstanten aus den globalen Bäumen⓪!* direkt (ohne Umweg über DATA-Puffer) hinter den Code kopiert.⓪!*)⓪ ⓪ PROCEDURE CopyDataToCode;⓪ BEGIN  ASSEMBLER⓪)CMPI.B  #50,D0         ; CONST (neu)⓪)BNE     FLKNOT3⓪)BTST    #8+4,D0        ; exportiert?⓪)BNE     useData        ;   ja -> in DATA ablegen⓪)BTST    #8+5,D0        ; importiert?⓪)BNE     FLKNOT3        ;   ja -> ignorieren⓪)TST.L   -8-14(A1,D2.L)  ;^letzte Ref⓪)BEQ     FLKNOT3        ;   Null -> ignorieren⓪ useData  ; umkopieren in den Code⓪)BSET    #2,-8-2(A1,D2.L)⓪)BNE     FLKNOT3        ; -> bereits bearbeitet⓪)MOVE.W  -8-16(A1,D2.L),D0 ;BYTELAENGE⓪)BEQ     add0w⓪)ADDQ    #1,D0⓪)BCLR    #0,D0⓪)MOVE.W  D0,-8-16(A1,D2.L) ;aufgerundete Länge im Tree setzen⓪)MOVE.L  D2,-(A7)⓪ ConsID3b MOVE.L  -8-20(A1,D2.L),(A4)+ ;KONSTANTE AUS BAUM KOPIEREN⓪)SUBQ.L  #4,D2⓪)SUBQ.W  #4,D0⓪)BGT     ConsID3b⓪)BEQ     ok2⓪); es sind 2 Byte zuviel kopiert worden⓪)SUBQ.L  #2,A4⓪ ok2:     MOVE.L  (A7)+,D2⓪); Strings im DATA müssen immer 0-terminiert werden:⓪ add0w:   MOVE.L  -8-10(A1,D2.L),D0 ;Typ⓪)CMP.L   StrPtr,D0⓪)BNE     notStrng⓪)MOVE.W  -8-16(A1,D2.L),D0 ;BYTELAENGE⓪)BEQ     add0w2⓪)BTST    #0,D0⓪)BEQ     isEven⓪); wenn String ungerade Länge hat, einfach letztes Byte löschen⓪)CLR.B   -1(A4)⓪)BRA     notStrng⓪ isEven   ; bei gerader Länge: prüfen, ob 0C am Ende, sonst eins anfügen⓪)TST.B   -1(A4)⓪)BEQ     notStrng⓪ add0w2:  CLR.W   (A4)+⓪)ADDQ.W  #2,-8-16(A1,D2.L) ;neue Länge im Tree setzen⓪ notStrng⓪ FLKNOT3:⓪ END⓪ END CopyDataToCode;⓪ ⓪ PROCEDURE FinishData;⓪"BEGIN⓪$ASSEMBLER⓪)MOVEM.L A2-A3,-(A7)⓪)MOVE.L  A4,DataCodeOffs⓪)MOVE.L  DataStart,A0⓪ lup20:   CMPA.L  DataPtr,A0⓪)BEQ     endOfD2⓪)MOVE.W  (A0)+,D0⓪)LSR     #1,D0⓪)TST.L   (A0)+          ; ^letzte Ref⓪)BEQ     lup21          ;   -> wenn Null, überspringen⓪)BRA     lup23⓪ lup22:   MOVE.W  (A0)+,(A4)+⓪ lup23:   DBRA    D0,lup22⓪)BRA     lup20⓪ lup21:   ADDA.W  D0,A0⓪)ADDA.W  D0,A0⓪)BRA     lup20⓪ endOfD2:⓪); nun auch die globalen CONSTs aus dem Tree umtragen⓪)LEA    CopyDataToCode,A5⓪)JSR    TravTr          ; ALLE verbliebenen Bäume durchgehen⓪)MOVEM.L (A7)+,A2-A3⓪$END⓪"END FinishData;⓪ ⓪ (*EOF*)⓪ ə
  2. (* $00002637$00003245$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$000010EE$FFFCF6BE$00009277$FFFCF6BE$000040AF$FFFCF6BE$FFF7AB10$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFF6EC04$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$00007D80$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BE$FFFCF6BEÇ$000010EET........T.......T......T.......T.......T.......T.......T.......T.......T.......$000090DC$0000916F$FFE030A8$FFE030A8$0000917C$0000916F$0000918F$0000925A$000010F8$00001019$00001083$00001022$00001083$000010F5$00008FF0$00009012ÕÇâ*)
  3.